﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Domain.Common;
using Domain.Repositories;

namespace Domain.Model
{
	/// <summary>
	///     Describes a session between more than two contacts.
	/// </summary>
	public class Session : AggregateRoot
	{
		private readonly ICollection<Contact> _contacts = new Collection<Contact>();
		public ICollection<Contact> Contacts
		{
			get
			{
				// always return a copy of _contacts.
				return _contacts.Select(c => c).ToList();
			}
		}

		public Session(Messenger messenger)
		{
			Messenger = messenger;
		}

		public Messenger Messenger
		{
			get;
			private set;
		}

		public void SendMessage(Message message)
		{
			foreach (var contact in _contacts.Where(c => c != ContactManager.Myself))
				Messenger.SendMessage(contact, message);
		}

		public void AttachContact(Contact contact)
		{
			// To add contact for constructor and clone.
			if (_contacts.Select(c => c.ID).Contains(contact.ID))
				this.ContactInfoChanged(contact);
			else
				_contacts.Add(contact);
		}

		public void InviteContact(Contact contact)
		{
			if (_contacts.Select(c => c.ID).Contains(contact.ID))
				return;
			
			_contacts.Add(contact);
			// TODO: fires the event ContactsChanged to the others.
		}

		// Hanlder for message SomeoneJoined
		public void ContactJoined(Contact contact)
		{
			//TODO: update the contacts list.
			if (_contacts.Select(c => c.ID).Contains(contact.ID))
				this.ContactInfoChanged(contact);
			else
				_contacts.Add(contact);
		}

		// Handler for message SomeoneChanged
		public void ContactInfoChanged(Contact contact)
		{
			//TODO: update the displayed nickname of contact, as so on.
			var older = _contacts.First(c => c.ID.Equals(contact.ID));
			if (older == null)
				return;

			_contacts.Remove(older);
			_contacts.Add(contact);
		}
	}
}